#include <iostream>
#include <fstream>
#include <cstring>
#include <nng/nng.h>
#include <nng/protocol/reqrep0/rep.h>
#include <thread>


constexpr int BUFFER_SIZE = 4096;

void fatal(const char* func, int rv) {
    std::cerr << func << ": " << nng_strerror(rv) << std::endl;
    exit(1);
}

void handleRequest(nng_socket sock, nng_msg* pmsg) {
    int rv;
    nng_msg* msg = pmsg;

    std::thread::id thread_id = std::this_thread::get_id();
    std::cout << "[t:"<< thread_id << "]server handle request." << std::endl;
    // 获取客户端请求的文件名
    const char* filename = static_cast<const char*>(nng_msg_body(msg));
    std::cout << "client request filename: " << filename << std::endl;
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        // 文件打开失败，发送错误消息给客户端
        nng_msg_free(msg);
        if ((rv = nng_msg_alloc(&msg, 0))!= 0) {
            fatal("nng_msg_alloc", rv);
        }
        const char* error_msg = "File not found";
        nng_msg_append(msg, error_msg, strlen(error_msg));
    }
    else {
        // 文件打开成功，读取文件内容并发送给客户端
        nng_msg_free(msg);
        if ((rv = nng_msg_alloc(&msg, 0)) != 0) {
            fatal("nng_msg_alloc", rv);
        }
        char buffer[BUFFER_SIZE];
        while (file.read(buffer, BUFFER_SIZE)) {
            nng_msg_append(msg, buffer, BUFFER_SIZE);
        }
        auto bytes_read = file.gcount();
        if (bytes_read > 0) {
            nng_msg_append(msg, buffer, bytes_read);
        }
        file.close();
    }
    // 发送响应消息给客户端
    if ((rv = nng_sendmsg(sock, msg, 0)) != 0) {
        fatal("nng_sendmsg", rv);
    }
}

int main() {
    nng_socket sock;
    int rv;
    if ((rv = nng_rep0_open(&sock)) != 0) {
        fatal("nng_rep0_open", rv);
    }
    if ((rv = nng_listen(sock, "tcp://127.0.0.1:5555", nullptr, 0)) != 0) {
        fatal("nng_listen", rv);
    }

    while (true) {
        nng_msg* msg;
        if ((rv = nng_recvmsg(sock, &msg, 0)) != 0) {
            fatal("nng_recvmsg", rv);
        }

        nng_ctx ctx1;
        nng_ctx_open(&ctx1, sock);

        std::cout << "server get new request." << std::endl;
        // 创建一个新线程来处理请求
        std::thread t(handleRequest, sock, msg);
        t.detach();
    }

    nng_close(sock);
    return 0;
}